Add expense activity history foundation - #10237
Add expense activity history foundation#10237Prangshuman Das (t-prda) wants to merge 29 commits into
Conversation
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: d9178a5c-c5ff-43a4-b9cb-877ec18618fa
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: d9178a5c-c5ff-43a4-b9cb-877ec18618fa
|
The changed permission-set source file is named Knowledge: Line mapping was unavailable, so this was posted as an issue comment. 👍 useful · ❤️ especially valuable · 👎 wrong - reply with why · AL review agent v1.32.4 |
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: d9178a5c-c5ff-43a4-b9cb-877ec18618fa
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: d9178a5c-c5ff-43a4-b9cb-877ec18618fa
Apply partial-record reads and mediate activity table access through the API and factbox pages. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: d9178a5c-c5ff-43a4-b9cb-877ec18618fa
|
The filename comment refers to a pre-existing repository file, |
|
Capability-specific behaviour is still selected with a Knowledge: Line mapping was unavailable, so this was posted as an issue comment. 👍 useful · ❤️ especially valuable · 👎 wrong - reply with why · AL review agent v1.32.4 |
Remove retention registration from the foundation and track install, upgrade, refresh, permission, and audit semantics separately. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: d9178a5c-c5ff-43a4-b9cb-877ec18618fa
Select query-backed keys, lock wire-token errors, avoid UI handlers, and restore setup backups before disabled-isolation tests. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: d9178a5c-c5ff-43a4-b9cb-877ec18618fa
|
ProcessExpenseReportLines calls CreateSalesDocument for every posted expense line, and CreateSalesDocument re-runs SalesHeader.FindFirst on the persistent Sales Header table each time to locate an open invoice for the same customer/currency/posting-date combination. That creates an N+1 lookup pattern during posting; cache or pre-group the target sales document (and its next line number) for the duration of the loop instead of querying Sales Header per line. Knowledge: Line mapping was unavailable, so this was posted as an issue comment. 👍 useful · ❤️ especially valuable · 👎 wrong - reply with why · AL review agent v1.32.4 |
|
The new audit logging trusts caller-supplied expense-user numbers for approval actions and records them as the actor without first binding them to the report's configured approver. In the internal Agent judgement — not directly backed by a BCQuality knowledge article. Line mapping was unavailable, so this was posted as an issue comment. 👍 useful · ❤️ especially valuable · 👎 wrong - reply with why · AL review agent v1.32.4 |
|
The changed file Knowledge: Line mapping was unavailable, so this was posted as an issue comment. 👍 useful · ❤️ especially valuable · 👎 wrong - reply with why · AL review agent v1.32.4 |
|
ExpenseActivityLogAPITest.E2EActivityLogScenario uses a modal-page handler that always invokes OK without any enqueue/dequeue expectation, and the test does not prove which Expenses dialog was shown. That matches the hardcoded-handler anti-pattern: the scenario can stay green even if the wrong UI interaction occurs, so it does not reliably verify the headless UI path it claims to cover. Knowledge: Line mapping was unavailable, so this was posted as an issue comment. 👍 useful · ❤️ especially valuable · 👎 wrong - reply with why · AL review agent v1.32.4 |
|
This PR modifies Knowledge: Line mapping was unavailable, so this was posted as an issue comment. 👍 useful · ❤️ especially valuable · 👎 wrong - reply with why · AL review agent v1.32.4 |
Grant direct read through Expense Mgmt. Read like the other factbox source tables. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: d9178a5c-c5ff-43a4-b9cb-877ec18618fa
|
Knowledge: Line mapping was unavailable, so this was posted as an issue comment. 👍 useful · ❤️ especially valuable · 👎 wrong - reply with why · AL review agent v1.32.4 |
| var | ||
| SubmitterExpenseUser: Record "Expense User"; | ||
| ApproverExpenseUser: Record "Expense User"; | ||
| ExpenseReportHeader: Record "Expense Report Header"; | ||
| ExpenseActivityLogEntry: Record "Expense Activity Log Entry"; | ||
| ExpenseReportApprovalMgt: Codeunit "Expense Report Approval Mgmt"; |
There was a problem hiding this comment.
ReopeningApprovedReportIsLogged uses CurrentUserExpenseUser later in the method, but that record is not declared in the method's var block. The new test codeunit will not compile until the local variable is added.
| var | |
| SubmitterExpenseUser: Record "Expense User"; | |
| ApproverExpenseUser: Record "Expense User"; | |
| ExpenseReportHeader: Record "Expense Report Header"; | |
| ExpenseActivityLogEntry: Record "Expense Activity Log Entry"; | |
| ExpenseReportApprovalMgt: Codeunit "Expense Report Approval Mgmt"; | |
| var | |
| SubmitterExpenseUser: Record "Expense User"; | |
| ApproverExpenseUser: Record "Expense User"; | |
| CurrentUserExpenseUser: Record "Expense User"; | |
| ExpenseReportHeader: Record "Expense Report Header"; | |
| ExpenseActivityLogEntry: Record "Expense Activity Log Entry"; | |
| ExpenseReportApprovalMgt: Codeunit "Expense Report Approval Mgmt"; |
👍 useful · ❤️ especially valuable · 👎 wrong - reply with why · AL review agent v1.32.4
|
This promoted navigation group is captioned 'Expense', but the actions inside operate on the current expense report. Using the entity name 'Expense Report' matches the standard promoted-group naming guidance and aligns this page with the posted expense report page added in the same change. Suggested fix (apply manually — could not be anchored as a one-click suggestion): Caption = 'Expense Report';Knowledge: Line mapping was unavailable, so this was posted as an issue comment. 👍 useful · ❤️ especially valuable · 👎 wrong - reply with why · AL review agent v1.32.4 |
|
The promoted action group uses the nonstandard caption 'Approval'. BC's standard workflow group name is 'Approve', so keeping 'Approval' here makes this action bar diverge from the platform's established document-page vocabulary. Suggested fix (apply manually — could not be anchored as a one-click suggestion): Caption = 'Approve';Knowledge: Line mapping was unavailable, so this was posted as an issue comment. 👍 useful · ❤️ especially valuable · 👎 wrong - reply with why · AL review agent v1.32.4 |
|
This promoted navigation group is captioned 'Expense', but the actions inside are tied to the current expense report record. The standard pattern is to use an entity-named group, so captioning it 'Expense Report' keeps the ribbon consistent with native BC pages. Suggested fix (apply manually — could not be anchored as a one-click suggestion): Caption = 'Expense Report';Knowledge: Line mapping was unavailable, so this was posted as an issue comment. 👍 useful · ❤️ especially valuable · 👎 wrong - reply with why · AL review agent v1.32.4 |
|
The new reimbursement-notification flow sends the employee email in the "On-Behalf-Of" header and the posted expense report id to the external Expense Agent service, but this path never checks the Expense Agent privacy notice before calling SendReimbursementNotification. The integration should confirm or verify its own notice on this request path before transferring data externally. Knowledge: Line mapping was unavailable, so this was posted as an issue comment. 👍 useful · ❤️ especially valuable · 👎 wrong - reply with why · AL review agent v1.32.4 |
|
The new Expense Report Header table relies on table-level DataClassification and leaves 25 stored fields without explicit field classifications, including "Expense User No.", "Expense User Name", "Description", and "Spend Request No.". Table-level classification does not satisfy field-level privacy classification requirements, so these personal and customer-bearing fields ship under-classified. Knowledge:
Line mapping was unavailable, so this was posted as an issue comment. 👍 useful · ❤️ especially valuable · 👎 wrong - reply with why · AL review agent v1.32.4 |
|
The new Posted Expense Report Header table also relies on table-level DataClassification and leaves 25 stored fields without explicit field classifications, including "Expense User No.", "Expense User Name", "Description", and "Spend Request No.". Field-level classifications are still required for these persisted values. Knowledge:
Line mapping was unavailable, so this was posted as an issue comment. 👍 useful · ❤️ especially valuable · 👎 wrong - reply with why · AL review agent v1.32.4 |
Remove the API page from human Expense Management object permissions; the FactBox remains available there. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: d9178a5c-c5ff-43a4-b9cb-877ec18618fa
| ExpenseActivityLogEntry.Get(EntryNumber); | ||
| ExpenseActivityLogEntry."Source Table ID" := Database::"Posted Expense Report Header"; | ||
| ExpenseActivityLogEntry."Source Record System ID" := PostedExpenseReportHeader.SystemId; | ||
| ExpenseActivityLogEntry.Modify(false); |
There was a problem hiding this comment.
"Expense Activity Log Entry" declares OnModify/OnRename triggers that Error('Activity log entries cannot be modified.') to enforce an append-only audit trail. However, ReassignExpenseReportEntriesToPosted calls ExpenseActivityLogEntry.Modify(false) to rewrite "Source Table ID"/"Source Record System ID" on existing entries, which deliberately bypasses that trigger. This is a cross-cutting concern (data-integrity guarantee vs. security/auditability expectation): the table's public contract advertises immutable entries, but any code holding tabledata permission can silently rewrite an entry's source identity the same way, undermining the audit trail's tamper-evidence. Consider exposing a dedicated, narrowly-scoped reassignment API (e.g. a SQL-level or trigger-aware update path with its own validation) rather than relying on Modify(false) to route around the immutability guard, or documenting explicitly that the guard only protects against direct user/API edits and not internal reassignment.
Agent judgement — not directly backed by a BCQuality knowledge article.
👍 useful · ❤️ especially valuable · 👎 wrong - reply with why · AL review agent v1.32.4
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: d9178a5c-c5ff-43a4-b9cb-877ec18618fa
|
Superseded by a replacement PR from the same branch to reset stale review and CI history after the design was finalized. |
|
This change adds another branch to the existing Knowledge: Line mapping was unavailable, so this was posted as an issue comment. 👍 useful · ❤️ especially valuable · 👎 wrong - reply with why · AL review agent v1.32.4 |
|
The new reimbursement-notification path sends data to the external Expense Agent service without checking the custom privacy notice on the sending path. Both TrySendReimbursementNotification() and CheckAndSendReimbursementNotification() proceed from configuration checks straight to EAHttpClient.SendReimbursementNotification(ExpenseUser2."E-mail", PostedExpReportHeader.SystemId), so the expense user's email address and report identifier can be transferred even though this code never calls ConfirmPrivacyNoticeApproval(...) or GetPrivacyNoticeApprovalState(...) before the request. Knowledge: Line mapping was unavailable, so this was posted as an issue comment. 👍 useful · ❤️ especially valuable · 👎 wrong - reply with why · AL review agent v1.32.4 |
|
Knowledge: Line mapping was unavailable, so this was posted as an issue comment. 👍 useful · ❤️ especially valuable · 👎 wrong - reply with why · AL review agent v1.32.4 |
|
Suggested fix (apply manually — could not be anchored as a one-click suggestion): EntryRecIDLbl: Label '%1 %2', Comment = '%1 = Table Caption, %2 = Document No.', Locked = true;Knowledge: Line mapping was unavailable, so this was posted as an issue comment. 👍 useful · ❤️ especially valuable · 👎 wrong - reply with why · AL review agent v1.32.4 |
|
This page is keyed by SystemId, but the Knowledge: Line mapping was unavailable, so this was posted as an issue comment. 👍 useful · ❤️ especially valuable · 👎 wrong - reply with why · AL review agent v1.32.4 |
|
This page is keyed by SystemId, but the Knowledge: Line mapping was unavailable, so this was posted as an issue comment. 👍 useful · ❤️ especially valuable · 👎 wrong - reply with why · AL review agent v1.32.4 |
|
This page is keyed by SystemId, but the Knowledge: Line mapping was unavailable, so this was posted as an issue comment. 👍 useful · ❤️ especially valuable · 👎 wrong - reply with why · AL review agent v1.32.4 |
Summary
Validation
historyActorRolewere verified to fail closedFixes AB#644172
Related: AB#639704